/****************************************************************************
 * Elisa 1.0                                                                *
 *--------------------------------------------------------------------------*
 * Author: Laurent Granvilliers, Vincent Sorin                              *
 * Copyright (c) 2004 Laboratoire d'Informatique de Nantes Atlantique       *
 *--------------------------------------------------------------------------*
 * Elisa is distributed WITHOUT ANY WARRANTY. Read the associated           *
 * COPYRIGHT file for more details.                                         *
 *--------------------------------------------------------------------------*
 * elisa_natural_interval_form.h                                            *
 ****************************************************************************/

/**
 * @file elisa_natural_interval_form.h
 * @brief Interval evaluation of expressions
 */


#ifndef _ELISA_NATURAL_INTERVAL_FORM_H
#define _ELISA_NATURAL_INTERVAL_FORM_H

#include <vector>
#include "elisa_defs.h"
#include "elisa_real_expr.h"
#include "elisa_interval_form.h"
#include "elisa_interval.h"

NAMESPACE_ELISA

/**
 * @ingroup Interval
 * @class NaturalIntervalFormNode
 * @brief Base class for interval evaluation
 */
class NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 */
	NaturalIntervalFormNode()
	{
		m_isConst = false;
	}

	/**
 	 * Destructor
 	 */
	virtual ~NaturalIntervalFormNode()
	{
	}

	/**
 	 * Set a boolean at each node, true if the expression contains x
 	 */
	virtual bool toConstNodes(const RealVarImpl & x) = 0;

	/**
 	 * Return the lastly computed interval evaluation
 	 */
	FORM_RTYPE value() CONST
	{
		return m_value;
	}

	/**
 	 * Set the computed interval evaluation
 	 * @param I the computed interval
 	 */
	void setValue(const Interval & I)
	{
		m_value = I;
	}

	/**
 	 * To know if the expression must be evaluated for lazy evaluation
 	 * @return true if the expression is not constant
 	 */
	bool isNotConstant() const
	{
		return !m_isConst;
	}

	/**
 	 * Return the interval evaluation
 	 * @return the evaluation of the node
 	 */
	virtual FORM_RTYPE eval() CONST = 0;

	/**
 	 * Return the interval evaluation over a box
 	 * @param b the box used to evaluate
 	 * @return the evaluation of the node over b
 	 */
	virtual FORM_RTYPE eval(Box *b) CONST = 0;

	/**
 	 * Return the interval evaluation
 	 * @return the evaluation of the node
 	 */
	virtual FORM_RTYPE evalLazy() CONST = 0;

	/**
 	 * Compute the interval evaluation and set interval evaluation
 	 * of each sub-term at the node
 	 */
	virtual void evalForward() = 0;

	/**
 	 * Propagate the changement of value to the subterms.
 	 * of each sub-term at the node
 	 * @param i the value of the node
 	 * @return false if one subterm is inconsistant
 	 */
	virtual bool propagBackward(const Interval & i) = 0;

	/**
 	 * Return the derivative wrt. v using the forward mode
 	 * @param v the variable used for derivation
 	 * @return the derivative
 	 */
	virtual FORM_RTYPE deriv(const RealVarImpl & v) CONST = 0;

	/**
 	 * Return the derivative wrt. v using the forward mode
 	 * @param v the variable used for derivation
 	 * @return the derivative
 	 */
	virtual FORM_RTYPE derivLazy() CONST = 0;

protected:
	// @var interval evaluation of expression
	Interval m_value;
	// @var boolean for constant expressions
	bool m_isConst;
};

/**
 * @ingroup Interval
 * @class NaturalIntervalFormConst
 * @brief Class for interval evaluation of a constant node
 */
class NaturalIntervalFormConst : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param x the value of the node
 	 */
	NaturalIntervalFormConst (const Interval & x)
	{
		m_value = x;
	}

	/**
 	 * Destructor
 	 */
	~NaturalIntervalFormConst ()
	{
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		return false;
	}

	FORM_RTYPE eval() CONST
	{
		return m_value;
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return m_value;
	}

	FORM_RTYPE evalLazy() CONST
	{
		return m_value;
	}

	void evalForward()
	{
	}

	virtual bool propagBackward(const Interval & i)
	{
		return m_value.overlaps(i);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return Interval::Zero;
	}


	FORM_RTYPE derivLazy() CONST
	{
		return Interval::Zero;
	}
	//@}

private:
	// Copy protection
	NaturalIntervalFormConst (const NaturalIntervalFormConst & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormConst & operator=(const NaturalIntervalFormConst & x)
	{
	}
};

/**
 * @ingroup Interval
 * @class NaturalIntervalFormVar
 * @brief Class for interval evaluation of a variable node
 */
class NaturalIntervalFormVar : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param x the RealVarImplementation used for evaluation
 	 */
	NaturalIntervalFormVar (RealVarImpl & x)
	{
		m_var = &x;
	}

	/**
 	 * Destructor
 	 */
	~NaturalIntervalFormVar ()
	{
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (x == (*m_var)) {
			m_isConst = false; // non constant wrt. x
			return false;
		} else {
			return true;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return m_var->domain();
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return m_var->domain(b);
	}

	FORM_RTYPE evalLazy() CONST
	{
		return m_var->domain();
	}

	void evalForward()
	{
		m_value = m_var->domain();
	}

	virtual bool propagBackward(const Interval& i)
	{
		Interval save(m_value);
		if (m_value.intersect(i) != save) {
			m_var->setDomain(m_value);
		}
		return !(m_value.isEmpty());
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return(((*m_var) == v) ? Interval::One : Interval::Zero);
	}


	FORM_RTYPE derivLazy() CONST
	{
		return(this->isNotConstant() ? Interval::One : Interval::Zero);
	}
	//@}

private:
	RealVarImpl *m_var; // the variable at this node

	// Copy protection
	NaturalIntervalFormVar (const NaturalIntervalFormVar & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormVar & operator=(const NaturalIntervalFormVar & x)
	{
	}
};

/**
 * @ingroup Interval
 * @class NaturalIntervalFormAdd
 * @brief Class for interval evaluation of the addition
 */
class NaturalIntervalFormAdd : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param l the left child of the node
 	 * @param r the right child of the node
 	 */
	NaturalIntervalFormAdd (NaturalIntervalFormNode *l,
	                        NaturalIntervalFormNode *r)
	{
		_l = l; _r = r;
	}

	/**
 	 * Destructor
 	 * @post the left and the right children are deleted
 	 */
	~NaturalIntervalFormAdd()
	{
		delete _l;
		delete _r;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_l->toConstNodes(x) && _r->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return _l->eval() + _r->eval();
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return _l->eval(b) + _r->eval(b);
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return _l->evalLazy() + _r->evalLazy();
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_l->evalForward();
		_r->evalForward();
		m_value = _l->value() + _r->value();
	}

	virtual
	bool propagBackward(const Interval & i)
	{
		Interval li = _l->value();
		li.intersect(i - _r->value());
		Interval ri = _r->value();
		ri.intersect(i - _l->value());

		return _l->propagBackward(li) && _r->propagBackward(ri);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return _l->deriv(v) + _r->deriv(v);
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return _l->derivLazy() + _r->derivLazy();
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_l;
	NaturalIntervalFormNode *_r;

	// Copy protection
	NaturalIntervalFormAdd & operator=(const NaturalIntervalFormAdd & x)
	{
	}
	NaturalIntervalFormAdd (const NaturalIntervalFormAdd & x) : NaturalIntervalFormNode(x)
	{
	}
};

/**
 * @ingroup Interval
 * @class NaturalIntervalFormSum
 * @brief Class for interval evaluation of the n-ary addition
 */
class NaturalIntervalFormSum : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 */
	NaturalIntervalFormSum ()
	{
	}

	/**
 	 * Destructor
 	 * @post all children are deleted
 	 */
	~NaturalIntervalFormSum ()
	{
		for (unsigned int i = 0; i < _child.size(); ++i) {
			delete _child[i];
		}
	}

	/**
 	 * Adds a child in the last position
 	 * @param node the node to add
 	 */
	void addChild(NaturalIntervalFormNode *node)
	{
		_child.push_back(node);
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		m_isConst = true;
		unsigned int i = 0;
		while ((i < _child.size()) && m_isConst) {
			m_isConst = m_isConst && _child[i]->toConstNodes(x);
			++i;
		}
		return m_isConst;
	}

	FORM_RTYPE eval() CONST
	{
		Interval I = _child[0]->eval();
		for (unsigned int i = 1; i < _child.size(); ++i) {
			I += _child[i]->eval();
		}
		return I;
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		Interval I = _child[0]->eval(b);
		for (unsigned int i = 1; i < _child.size(); ++i) {
			I += _child[i]->eval(b);
		}
		return I;
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			Interval I = _child[0]->evalLazy();
			for (unsigned int i = 1; i < _child.size(); ++i) {
				I += _child[i]->evalLazy();
			}
			return I;
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_child[0]->evalForward();
		m_value = _child[0]->value();
		for (unsigned int i = 1; i < _child.size(); ++i) {
			_child[i]->evalForward();
			m_value += _child[i]->value();
		}
	}

	virtual bool propagBackward(const Interval & r)
	{
		Interval *child = new Interval[_child.size()];
		for (unsigned int i = 0; i < _child.size(); ++i) {
			child[i] = _child[i]->value();
		}
		for (unsigned int i = 0; i < _child.size(); ++i) {
			Interval ii = r;
			for (unsigned int j = 0; j < i; ++j) {
				ii = ii - child[j];
			}
			for (unsigned int j = i + 1; j < _child.size(); ++j) {
				ii = ii - child[j];
			}
			ii.intersect(child[i]);
			if (!(_child[i]->propagBackward(ii))) {
				return false;
			}
		}
		return true;
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		Interval I = _child[0]->deriv(v);
		for (unsigned int i = 1; i < _child.size(); ++i) {
			I += _child[i]->deriv(v);
		}
		return I;
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			Interval I = _child[0]->derivLazy();
			for (unsigned int i = 1; i < _child.size(); ++i) {
				I += _child[i]->derivLazy();
			}
			return I;
		} else return Interval(0);
	}
	//@}

private:
	std::vector<NaturalIntervalFormNode *> _child;

	// Copy protection
	NaturalIntervalFormSum & operator=(const NaturalIntervalFormSum & x)
	{
	}
	NaturalIntervalFormSum (const NaturalIntervalFormSum & x) : NaturalIntervalFormNode(x)
	{
	}
};



/**
 * @ingroup Interval
 * @class NaturalIntervalFormSub
 * @brief Class for interval evaluation of the substraction
 */
class NaturalIntervalFormSub : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param l the left child of the node
 	 * @param r the right child of the node
 	 */
	NaturalIntervalFormSub(NaturalIntervalFormNode *l,
	                       NaturalIntervalFormNode *r)
	{
		_l = l;
		_r = r;
	}

	/**
 	 * Destructor
 	 * @post the left and the right children are deleted
 	 */
	~NaturalIntervalFormSub()
	{
		delete _l;
		delete _r;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_l->toConstNodes(x) && _r->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else return false;
	}

	FORM_RTYPE eval() CONST
	{
		return _l->eval() - _r->eval();
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return _l->eval(b) - _r->eval(b);
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return _l->evalLazy() - _r->evalLazy();
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_l->evalForward();
		_r->evalForward();
		m_value = _l->value() - _r->value();
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval li = _l->value();
		li.intersect(i + _r->value());
		Interval ri = _r->value();
		ri.intersect(_l->value() - i);
		return(_l->propagBackward(li) && _r->propagBackward(ri));
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return _l->deriv(v) - _r->deriv(v);
	}


	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return _l->derivLazy() - _r->derivLazy();
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_l;
	NaturalIntervalFormNode *_r;

	// Copy protection
	NaturalIntervalFormSub & operator=(const NaturalIntervalFormSub & x)
	{
	}
	NaturalIntervalFormSub(const NaturalIntervalFormSub & x) : NaturalIntervalFormNode(x)
	{
	}
};



/**
 * @ingroup Interval
 * @class NaturalIntervalFormOpp
 * @brief Class for interval evaluation of the opposite
 */
class NaturalIntervalFormOpp : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param n the node that we want the opposed
 	 */
	NaturalIntervalFormOpp(NaturalIntervalFormNode *n)
	{
		_n = n;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormOpp()
	{
		delete _n;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return -_n->eval();
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return -_n->eval(b);
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return -_n->evalLazy();
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = -_n->value();
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval in = _n->value();
		in.intersect(-i);
		return _n->propagBackward(in);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return -_n->deriv(v);
		// (-u)' = -u'
	}


	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return -_n->derivLazy();
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_n;

	// Copy protection
	NaturalIntervalFormOpp(const NaturalIntervalFormOpp & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormOpp & operator=(const NaturalIntervalFormOpp & x)
	{
	}
};



/**
 * @ingroup Interval
 * @class NaturalIntervalFormMul
 * @brief Class for interval evaluation of the multiplication
 */
class NaturalIntervalFormMul : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param l the left child of the node
 	 * @param r the right child of the node
 	 */
	NaturalIntervalFormMul(NaturalIntervalFormNode *l,
	                       NaturalIntervalFormNode *r)
	{
		_l = l;
		_r = r;
	}

	/**
 	 * Destructor
 	 * @post the left and the right children are deleted
 	 */
	~NaturalIntervalFormMul()
	{
		delete _l;
		delete _r;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_l->toConstNodes(x) && _r->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return _l->eval() * _r->eval();
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return _l->eval(b) * _r->eval(b);
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return _l->evalLazy() * _r->evalLazy();
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_l->evalForward();
		_r->evalForward();
		m_value = _l->value() * _r->value();
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval li = _l->value();
		li.intersect(div_rel(i, _r->value(), _l->value()));
		Interval ri = _r->value();
		ri.intersect(div_rel(i, _l->value(), _r->value()));
		return(_l->propagBackward(li) && _r->propagBackward(ri));
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return _l->eval() * _r->deriv(v) + _l->deriv(v) * _r->eval();
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return _l->eval() * _r->derivLazy() + _l->derivLazy() * _r->eval();
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_l;
	NaturalIntervalFormNode *_r;

	// Copy protection
	NaturalIntervalFormMul & operator=(const NaturalIntervalFormMul & x)
	{
	}
	NaturalIntervalFormMul(const NaturalIntervalFormMul & x) : NaturalIntervalFormNode(x)
	{
	}
};



/**
 * @ingroup Interval
 * @class NaturalIntervalFormProd
 * @brief Class for interval evaluation of the n-ary multiplication
 */
class NaturalIntervalFormProd : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 */
	NaturalIntervalFormProd ()
	{
	}

	/**
 	 * Destructor
 	 * @post all children are deleted
 	 */
	~NaturalIntervalFormProd ()
	{
		for (unsigned int i = 0; i < _child.size(); ++i) {
			delete _child[i];
		}
	}

	/**
 	 * Adds a child in the last position
 	 * @param node the node to add
 	 */
	void addChild(NaturalIntervalFormNode *node)
	{
		_child.push_back(node);
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		m_isConst = true;
		unsigned int i = 0;
		while ((i < _child.size()) && m_isConst) {
			m_isConst = m_isConst && _child[i]->toConstNodes(x);
			++i;
		}
		return m_isConst;
	}

	FORM_RTYPE eval() CONST
	{
		Interval I = _child[0]->eval();
		for (unsigned int i = 1; i < _child.size(); ++i) {
			I *= _child[i]->eval();
		}
		return I;
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		Interval I = _child[0]->eval(b);
		for (unsigned int i = 1; i < _child.size(); ++i) {
			I *= _child[i]->eval(b);
		}
		return I;
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			Interval I = _child[0]->evalLazy();
			for (unsigned int i = 1; i < _child.size(); ++i) {
				I *= _child[i]->evalLazy();
			}
			return I;
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_child[0]->evalForward();
		m_value = _child[0]->value();
		for (unsigned int i = 1; i < _child.size(); ++i) {
			_child[i]->evalForward();
			m_value *= _child[i]->value();
		}
	}

	bool propagBackward(const Interval & r)
	{
		Interval *child = new Interval[_child.size()];
		for (unsigned int i = 0; i < _child.size(); ++i) {
			child[i] = _child[i]->value();
		}

		for (unsigned int i = 0; i < _child.size(); ++i) {
			Interval prod(1);
			for (unsigned int j = 0; j < i; ++j) {
				prod *= child[j];
			}

			for (unsigned int j = i + 1; j < _child.size(); ++j) {
				prod *= child[j];
			}
			Interval ii;
			ii = div_rel(r, prod, child[i]);
			if (!(_child[i]->propagBackward(ii))) {
				return false;
			}
		}
		return true;
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return deriv(v, 0);
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return derivLazy(0);
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	std::vector<NaturalIntervalFormNode *> _child;

	// Copy protection
	NaturalIntervalFormProd & operator=(const NaturalIntervalFormProd & x)
	{
	}
	NaturalIntervalFormProd (const NaturalIntervalFormProd & x) : NaturalIntervalFormNode(x)
	{
	}


	/// Given the product a0 * ... * aN, derivation of ai * ... * aN
	FORM_RTYPE deriv(const RealVarImpl & v, unsigned int i) const
	{
		// last child?
		if (i == _child.size() - 1) {
			return _child[i]->deriv(v);
		} else {
			// derivation of expression a * f => a * df + da * f
			return _child[i]->eval() * deriv(v, i + 1) +
			       _child[i]->deriv(v) * eval(i + 1);
		}
	}

	/// Given the product a0 * ... * aN, lazy derivation of ai * ... * aN
	FORM_RTYPE derivLazy(unsigned int i) const
	{
		// last child?
		if (i == _child.size() - 1) {
			return _child[i]->derivLazy();
		} else {
			// lazy derivation of expression a * f => a * df + da * f
			return _child[i]->eval() * derivLazy(i + 1) +
			       _child[i]->derivLazy() * eval(i + 1);
		}
	}

	/// Given the product a0 * ... * aN, evaluation of ai * ... * aN
	FORM_RTYPE eval(unsigned int i) const
	{
		// last child?
		if (i == _child.size() - 1) {
			return _child[i]->eval();
		}
		// evaluation of expression a * f = a * eval(f)
		else {
			return _child[i]->eval() * eval(i + 1);
		}
	}
};



/**
 * @ingroup Interval
 * @class NaturalIntervalFormDiv
 * @brief Class for interval evaluation of the division
 */
class NaturalIntervalFormDiv : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param l the left child of the node
 	 * @param r the right child of the node
 	 */
	NaturalIntervalFormDiv (NaturalIntervalFormNode *l,
	                        NaturalIntervalFormNode *r)
	{
		_l = l;
		_r = r;
	}

	/**
 	 * Destructor
 	 * @post the left and the right children are deleted
 	 */
	~NaturalIntervalFormDiv()
	{
		delete _l;
		delete _r;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_l->toConstNodes(x) && _r->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else return false;
	}

	FORM_RTYPE eval() CONST
	{
		return _l->eval() / _r->eval();
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return _l->eval(b) / _r->eval(b);
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant())
			return _l->evalLazy() / _r->evalLazy();
		else
			return m_value;
	}

	void evalForward()
	{
		_l->evalForward();
		_r->evalForward();
		m_value = _l->value() / _r->value();
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval li = _l->value();
		li.intersect(i * _r->value());
		Interval ri = _r->value();
		ri.intersect(div_rel(_l->value(), i, _r->value()));
		return _l->propagBackward(li) && _r->propagBackward(ri);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		_l->evalForward();
		_r->evalForward();
		return((_r->value() * _l->deriv(v) - _l->value() * _r->deriv(v)) /
		       (sqr(_r->value())));
	}


	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			_l->evalForward();
			_r->evalForward();
			return((_r->value() * _l->derivLazy() - _l->value() * _r->derivLazy()) /
			       (sqr(_r->value())));
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_l;
	NaturalIntervalFormNode *_r;

	// Copy protection
	NaturalIntervalFormDiv & operator=(const NaturalIntervalFormDiv & x)
	{
	}
	NaturalIntervalFormDiv(const NaturalIntervalFormDiv & x) : NaturalIntervalFormNode(x)
	{
	}
};

///

/**
 * @ingroup Interval
 * @class NaturalIntervalFormMin
 * @brief Class for interval evaluation of the min of two expressions
 */
class NaturalIntervalFormMin : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param l the left child of the node
 	 * @param r the right child of the node
 	 */
	NaturalIntervalFormMin (NaturalIntervalFormNode *l,
	                        NaturalIntervalFormNode *r)
	{
		_l = l; _r = r;
	}

	/**
 	 * Destructor
 	 * @post the left and the right children are deleted
 	 */
	~NaturalIntervalFormMin()
	{
		delete _l;
		delete _r;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_l->toConstNodes(x) && _r->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return minI(_l->eval(), _r->eval());
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return minI(_l->eval(), _r->eval());
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return minI(_l->evalLazy(), _r->evalLazy());
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_l->evalForward();
		_r->evalForward();
		m_value = minI(_l->value(), _r->value());
	}

	virtual
	bool propagBackward(const Interval & i)
	{
		Interval tmp;

		// left interval
		Interval leftInterval;
		tmp = i;
		tmp.intersect(_r->value());
		if (tmp.isEmpty()) {
			leftInterval = i;
			leftInterval.intersect(_l->value());
		} else {
			leftInterval = _l->value();
		}
		if (i.inf() > leftInterval.inf()) {
			leftInterval = Interval(i.inf(), leftInterval.sup());
		}
		bool l = _l->propagBackward(leftInterval);

		// right interval
		Interval rightInterval;

		tmp = i;
		tmp.intersect(_l->value());
		if (tmp.isEmpty()) {
			rightInterval = i;
			rightInterval.intersect(_r->value());
		} else {
			rightInterval = _r->value();
		}
		if (i.inf() > rightInterval.inf()) {
			rightInterval = Interval(i.inf(), rightInterval.sup());
		}
		bool r = _r->propagBackward(rightInterval);

		return l && r;
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return minI(_l->deriv(v), _r->deriv(v));
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return minI(_l->derivLazy(), _r->derivLazy());
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_l;
	NaturalIntervalFormNode *_r;

	// Copy protection
	NaturalIntervalFormMin & operator=(const NaturalIntervalFormMin & x)
	{
	}
	NaturalIntervalFormMin (const NaturalIntervalFormMin & x) : NaturalIntervalFormNode(x)
	{
	}
};



/**
 * @ingroup Interval
 * @class NaturalIntervalFormMax
 * @brief Class for interval evaluation of the max of two expressions
 */
class NaturalIntervalFormMax : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param l the left child of the node
 	 * @param r the right child of the node
 	 */
	NaturalIntervalFormMax (NaturalIntervalFormNode *l,
	                        NaturalIntervalFormNode *r)
	{
		_l = l; _r = r;
	}

	/**
 	 * Destructor
 	 * @post the left and the right children are deleted
 	 */
	~NaturalIntervalFormMax()
	{
		delete _l;
		delete _r;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_l->toConstNodes(x) && _r->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return Interval(maxI(_l->eval(), _r->eval()));
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return maxI(_l->eval(), _r->eval());
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return maxI(_l->evalLazy(), _r->evalLazy());
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_l->evalForward();
		_r->evalForward();
		m_value = maxI(_l->value(), _r->value());
	}

	virtual
	bool propagBackward(const Interval & i)
	{
		Interval tmp = i;

		// left interval
		Interval leftInterval;
		tmp.intersect(_r->value());
		if (tmp.isEmpty()) {
			leftInterval = i;
			leftInterval.intersect(_l->value());
		} else {
			leftInterval = _l->value();
		}
		if (i.sup() < leftInterval.sup()) {
			leftInterval = Interval(leftInterval.inf(), i.sup());
		}
		bool l = _l->propagBackward(leftInterval);

		// right interval
		Interval rightInterval;
		tmp = i;
		tmp.intersect(_l->value());
		if (tmp.isEmpty()) {
			rightInterval = i;
			rightInterval.intersect(_r->value());
		} else {
			rightInterval = _r->value();
		}
		// todo : check this computation
		if (i.sup() < rightInterval.sup()) {
			rightInterval = Interval(i.inf(), rightInterval.sup());
		}
		bool r = _r->propagBackward(rightInterval);

		return l && r;
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return maxI(_l->deriv(v), _r->deriv(v));
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return maxI(_l->derivLazy(), _r->derivLazy());
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_l;
	NaturalIntervalFormNode *_r;

	// Copy protection
	NaturalIntervalFormMax & operator=(const NaturalIntervalFormMax & x)
	{
	}
	NaturalIntervalFormMax (const NaturalIntervalFormMax & x) : NaturalIntervalFormNode(x)
	{
	}
};



///


/**
 * @ingroup Interval
 * @class NaturalIntervalFormSqr
 * @brief Class for interval evaluation of the square operation
 */
class NaturalIntervalFormSqr : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param n the node that we want the square value
 	 */
	NaturalIntervalFormSqr (NaturalIntervalFormNode *n)
	{
		_n = n;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormSqr()
	{
		delete _n;
	}
	/// @name Base class's virtual methods
	//@{

	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return sqr(_n->eval());
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return sqr(_n->eval(b));
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return sqr(_n->evalLazy());
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = sqr(_n->value());
	}

	virtual bool propagBackward(const Interval & i)
	{
		//Interval ni = _n->value();
		//ni.intersect(sqrt_rel(i, _n->value()));
		return _n->propagBackward(sqrt_rel(i, _n->value()));
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return Interval(2) * _n->eval() * _n->deriv(v);
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return Interval(2) * _n->eval() * _n->derivLazy();
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_n;

	// Copy protection
	NaturalIntervalFormSqr & operator=(const NaturalIntervalFormSqr & x)
	{
	}
	NaturalIntervalFormSqr(const NaturalIntervalFormSqr & x) : NaturalIntervalFormNode(x)
	{
	}
};



/**
 * @ingroup Interval
 * @class NaturalIntervalFormSqrt
 * @brief Class for interval evaluation of the square root operation
 */
class NaturalIntervalFormSqrt : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param n the node that we want the square root
 	 */
	NaturalIntervalFormSqrt (NaturalIntervalFormNode *n)
	{
		_n = n;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormSqrt()
	{
		delete _n;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return sqrt(_n->eval());
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return sqrt(_n->eval(b));
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return sqrt(_n->evalLazy());
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = sqrt(_n->value());
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval ni = _n->value();
		ni.intersect(sqr(i));
		return _n->propagBackward(ni);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return _n->deriv(v) / (Interval(2) * sqrt(_n->eval()));
		// sqrt(u)' = u' / (2*sqrt(u))
	}


	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return _n->derivLazy() / (Interval(2) * sqrt(_n->eval()));
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_n;

	// Copy protection
	NaturalIntervalFormSqrt(const NaturalIntervalFormSqrt & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormSqrt & operator=(const NaturalIntervalFormSqrt & x)
	{
	}
};



//
/**
 * @ingroup Interval
 * @class NaturalIntervalFormAbs
 * @brief Class for interval evaluation of the absolute value operation
 */
class NaturalIntervalFormAbs : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param n the node that we want the square root
 	 */
	NaturalIntervalFormAbs (NaturalIntervalFormNode *n)
	{
		_n = n;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormAbs()
	{
		delete _n;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return abs(_n->eval());
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return abs(_n->eval(b));
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return abs(_n->evalLazy());
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = abs(_n->value());
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval tmp(_n->value());
		tmp.intersect(invabs_rel(i, _n->value()));
		return _n->propagBackward(tmp);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return abs(_n->deriv(v));
	}


	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return abs(_n->derivLazy());
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_n;

	// Copy protection
	NaturalIntervalFormAbs(const NaturalIntervalFormAbs & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormAbs & operator=(const NaturalIntervalFormAbs & x)
	{
	}
};


//

/**
 * @ingroup Interval
 * @class NaturalIntervalFormPow
 * @brief Class for interval evaluation of the power operation
 */
class NaturalIntervalFormPow : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param n the node that we want the pow
 	 */
	NaturalIntervalFormPow(NaturalIntervalFormNode *n, int e)
	{
		_n = n;
		_e = e;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormPow()
	{
		delete _n;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return pow(_n->eval(), _e);
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return pow(_n->eval(b), _e);
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return pow(_n->evalLazy(), _e);
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = pow(_n->value(), _e);
	}

	virtual bool propagBackward(const Interval & i)
	{
		return _n->propagBackward(nth_root_rel(i, _e, _n->value()));
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return Interval(_e) * pow(_n->eval(), _e - 1) * _n->deriv(v);
		// pow(u,n)' = n*pow(u,n-1)*u'
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return Interval(_e) * pow(_n->eval(), _e - 1) * _n->derivLazy();
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_n;
	int _e;

	// Copy protection
	NaturalIntervalFormPow(const NaturalIntervalFormPow & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormPow & operator=(const NaturalIntervalFormPow & x)
	{
	}
};



/**
 * @ingroup Interval
 * @class NaturalIntervalFormLog
 * @brief Class for interval evaluation of the logarithm
 */
class NaturalIntervalFormLog : public NaturalIntervalFormNode
{
public:

	/**
 	 * Constructor
 	 * @param n the node that we want the logarithm
 	 */
	NaturalIntervalFormLog(NaturalIntervalFormNode *n)
	{
		_n = n;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormLog()
	{
		delete _n;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else return false;
	}

	FORM_RTYPE eval() CONST
	{
		return log(_n->eval());
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return log(_n->eval(b));
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return log(_n->evalLazy());
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = log(_n->value());
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval ni = _n->value();
		ni.intersect(exp(i));
		return _n->propagBackward(ni);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return _n->deriv(v) / _n->eval();
		// log(u)' = u' / u
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return _n->derivLazy() / _n->eval();
		} else
			return Interval(0);
	}
	//@}

private:
	NaturalIntervalFormNode *_n;

	// Copy protection
	NaturalIntervalFormLog(const NaturalIntervalFormLog & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormLog & operator=(const NaturalIntervalFormLog & x)
	{
	}
};



/**
 * @ingroup Interval
 * @class NaturalIntervalFormExp
 * @brief Class for interval evaluation of the exponential
 */
class NaturalIntervalFormExp : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param n the node that we want the exponential
 	 */
	NaturalIntervalFormExp(NaturalIntervalFormNode *n)
	{
		_n = n;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormExp()
	{
		delete _n;
	}


	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return exp(_n->eval());
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return exp(_n->eval(b));
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return exp(_n->evalLazy());
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = exp(_n->value());
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval ni = _n->value();
		ni.intersect(log(i));
		return _n->propagBackward(ni);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return _n->deriv(v) * exp(_n->eval());
		// exp(u)' = u' * exp(u)
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return _n->derivLazy() * exp(_n->eval());
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_n;

	// Copy protection
	NaturalIntervalFormExp(const NaturalIntervalFormExp & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormExp & operator=(const NaturalIntervalFormExp & x)
	{
	}
};


/**
 * @ingroup Interval
 * @class NaturalIntervalFormCos
 * @brief Class for interval evaluation of the cosine
 */
class NaturalIntervalFormCos : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param n the node that we want the cosine
 	 */
	NaturalIntervalFormCos(NaturalIntervalFormNode *n)
	{
		_n = n;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormCos()
	{
		delete _n;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return cos(_n->eval());
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return cos(_n->eval(b));
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return cos(_n->evalLazy());
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = cos(_n->value());
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval ni = _n->value();
		ni.intersect(acos_rel(i, _n->value()));
		return _n->propagBackward(ni);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return -(_n->deriv(v) * sin(_n->eval()));
		// cos(u)' = u' * (-sin(u))
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return -(_n->derivLazy() * sin(_n->eval()));
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_n;

	// Copy protection
	NaturalIntervalFormCos(const NaturalIntervalFormCos & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormCos & operator=(const NaturalIntervalFormCos & x)
	{
	}
};

/**
 * @ingroup Interval
 * @class NaturalIntervalFormACos
 * @brief Class for interval evaluation of the acosine
 */
class NaturalIntervalFormACos : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param n the node that we want the cosine
 	 */
	NaturalIntervalFormACos(NaturalIntervalFormNode *n)
	{
		_n = n;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormACos()
	{
		delete _n;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return acos(_n->eval());
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return acos(_n->eval(b));
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return acos(_n->evalLazy());
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = acos(_n->value());
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval ni = _n->value();
		ni.intersect(cos(i));
		return _n->propagBackward(ni);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return _n->deriv(v) / sqrt(Interval(1) - sqr(_n->eval()));
		// acos(u)' = 1/sqrt(1 - pow(u))
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return _n->derivLazy() / sqrt(Interval(1) - sqr(_n->eval()));
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_n;

	// Copy protection
	NaturalIntervalFormACos(const NaturalIntervalFormACos & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormACos & operator=(const NaturalIntervalFormACos & x)
	{
	}
};




/**
 * @ingroup Interval
 * @class NaturalIntervalFormSin
 * @brief Class for interval evaluation of the sine
 */
class NaturalIntervalFormSin : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param n the node that we want the sin
 	 */
	NaturalIntervalFormSin(NaturalIntervalFormNode *n)
	{
		_n = n;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormSin()
	{
		delete _n;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return sin(_n->eval());
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return sin(_n->eval(b));
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant())
			return sin(_n->evalLazy());
		else
			return m_value;
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = sin(_n->value());
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval ni = _n->value();
		ni.intersect(asin_rel(i, _n->eval()));
		return _n->propagBackward(ni);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return _n->deriv(v) * cos(_n->eval());
		// sin(u)' = u' * (cos(u))
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return _n->derivLazy() * cos(_n->eval());
		} else
			return Interval(0);
	}
	//@}

private:
	NaturalIntervalFormNode *_n;

	// Copy protection
	NaturalIntervalFormSin(const NaturalIntervalFormSin & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormSin & operator=(const NaturalIntervalFormSin & x)
	{
	}
};


/**
 * @ingroup Interval
 * @class NaturalIntervalFormASin
 * @brief Class for interval evaluation of the arc sine
 */
class NaturalIntervalFormASin : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param n the node that we want the sin
 	 */
	NaturalIntervalFormASin(NaturalIntervalFormNode *n)
	{
		_n = n;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormASin()
	{
		delete _n;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else return false;
	}

	FORM_RTYPE eval() CONST
	{
		return asin(_n->eval());
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return asin(_n->eval(b));
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return asin(_n->evalLazy());
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = asin(_n->value());
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval ni = _n->value();
		ni.intersect(sin(i));
		return _n->propagBackward(ni);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return -(_n->deriv(v) / sqrt(Interval(1) - sqr(_n->eval())));
		// asin(u)' = -(u')/Racine(1 - sqr(u))
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return -(_n->derivLazy() / sqrt(Interval(1) - sqr(_n->eval())));
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_n;

	// Copy protection
	NaturalIntervalFormASin(const NaturalIntervalFormASin & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormASin & operator=(const NaturalIntervalFormASin & x)
	{
	}
};


/**
 * @ingroup Interval
 * @class NaturalIntervalFormTan
 * @brief Class for interval evaluation of the tangent
 */
class NaturalIntervalFormTan : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param n the node that we want the tan
 	 */
	NaturalIntervalFormTan(NaturalIntervalFormNode *n)
	{
		_n = n;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormTan()
	{
		delete _n;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return tan(_n->eval());
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return tan(_n->eval(b));
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return tan(_n->evalLazy());
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = tan(_n->value());
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval ni = _n->value();
		ni.intersect(atan_rel(i, _n->value()));
		return _n->propagBackward(ni);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return _n->deriv(v) * Interval(1 + sqr(tan(_n->eval())));
		// tan(u)' = u' * (1 + tan^2(u))
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return _n->derivLazy() * Interval(1 + sqr(tan(_n->eval())));
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_n;

	// Copy protection
	NaturalIntervalFormTan(const NaturalIntervalFormTan & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormTan & operator=(const NaturalIntervalFormTan & x)
	{
	}
};



/**
 * @ingroup Interval
 * @class NaturalIntervalFormAtan
 * @brief Class for interval evaluation of the arc-tangent
 */
class NaturalIntervalFormAtan : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param n the node that we want the atan
 	 */
	NaturalIntervalFormAtan(NaturalIntervalFormNode *n)
	{
		_n = n;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormAtan()
	{
		delete _n;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return atan(_n->eval());
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return atan(_n->eval(b));
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return atan(_n->evalLazy());
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = atan(_n->value());
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval ni = _n->value();
		ni.intersect(tan(i));
		return _n->propagBackward(ni);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return _n->deriv(v) / Interval(1 + sqr(_n->eval()));
		// atan(u)' = u' / (1 + u^2)
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return _n->derivLazy() / Interval(1 + sqr(_n->eval()));
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_n;

	// Copy protection
	NaturalIntervalFormAtan(const NaturalIntervalFormAtan & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormAtan & operator=(const NaturalIntervalFormAtan & x)
	{
	}
};



/**
 * @ingroup Interval
 * @class NaturalIntervalFormCosh
 * @brief Class for interval evaluation of the hyperbolic cosine
 */
class NaturalIntervalFormCosh : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param n the node that we want the cosine
 	 */
	NaturalIntervalFormCosh(NaturalIntervalFormNode *n)
	{
		_n = n;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormCosh()
	{
		delete _n;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return cosh(_n->eval());
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return cosh(_n->eval(b));
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return cosh(_n->evalLazy());
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = cosh(_n->value());
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval ni = _n->value();
		ni.intersect(acosh_rel(i, _n->value()));
		return _n->propagBackward(ni);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return -(_n->deriv(v) * sinh(_n->eval()));
		// cosh(u)' = u' * (-sinh(u))
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return -(_n->derivLazy() * sinh(_n->eval()));
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_n;

	// Copy protection
	NaturalIntervalFormCosh(const NaturalIntervalFormCosh & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormCosh & operator=(const NaturalIntervalFormCosh & x)
	{
	}
};

/**
 * @ingroup Interval
 * @class NaturalIntervalFormACosh
 * @brief Class for interval evaluation of the acosine
 */
class NaturalIntervalFormACosh : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param n the node that we want the cosine
 	 */
	NaturalIntervalFormACosh(NaturalIntervalFormNode *n)
	{
		_n = n;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormACosh()
	{
		delete _n;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return acosh(_n->eval());
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return acosh(_n->eval(b));
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return acosh(_n->evalLazy());
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = acosh(_n->value());
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval ni = _n->value();
		ni.intersect(cosh(i));
		return _n->propagBackward(ni);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return _n->deriv(v) / sqrt(Interval(1) - sqr(_n->eval()));
		// acosh(u)' = 1/sqrt(1 - pow(u))
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return _n->derivLazy() / sqrt(Interval(1) - sqr(_n->eval()));
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_n;

	// Copy protection
	NaturalIntervalFormACosh(const NaturalIntervalFormACosh & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormACosh & operator=(const NaturalIntervalFormACosh & x)
	{
	}
};



/**
 * @ingroup Interval
 * @class NaturalIntervalFormSinh
 * @brief Class for interval evaluation of the sine
 */
class NaturalIntervalFormSinh : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param n the node that we want the sin
 	 */
	NaturalIntervalFormSinh(NaturalIntervalFormNode *n)
	{
		_n = n;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormSinh()
	{
		delete _n;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return sinh(_n->eval());
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return sinh(_n->eval(b));
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant())
			return sinh(_n->evalLazy());
		else
			return m_value;
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = sinh(_n->value());
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval ni = _n->value();
		ni.intersect(asinh_rel(i, _n->eval()));
		return _n->propagBackward(ni);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return _n->deriv(v) * cosh(_n->eval());
		// sinh(u)' = u' * (cosh(u))
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return _n->derivLazy() * cosh(_n->eval());
		} else
			return Interval(0);
	}
	//@}

private:
	NaturalIntervalFormNode *_n;

	// Copy protection
	NaturalIntervalFormSinh(const NaturalIntervalFormSinh & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormSinh & operator=(const NaturalIntervalFormSinh & x)
	{
	}
};


/**
 * @ingroup Interval
 * @class NaturalIntervalFormASinh
 * @brief Class for interval evaluation of the arc sine
 */
class NaturalIntervalFormASinh : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param n the node that we want the sin
 	 */
	NaturalIntervalFormASinh(NaturalIntervalFormNode *n)
	{
		_n = n;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormASinh()
	{
		delete _n;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else return false;
	}

	FORM_RTYPE eval() CONST
	{
		return asinh(_n->eval());
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return asinh(_n->eval(b));
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return asinh(_n->evalLazy());
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = asinh(_n->value());
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval ni = _n->value();
		ni.intersect(sinh(i));
		return _n->propagBackward(ni);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return -(_n->deriv(v) / sqrt(Interval(1) - sqr(_n->eval())));
		// asinh(u)' = -(u')/Racine(1 - sqr(u))
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return -(_n->derivLazy() / sqrt(Interval(1) - sqr(_n->eval())));
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_n;

	// Copy protection
	NaturalIntervalFormASinh(const NaturalIntervalFormASinh & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormASinh & operator=(const NaturalIntervalFormASinh & x)
	{
	}
};



/**
 * @ingroup Interval
 * @class NaturalIntervalFormTanh
 * @brief Class for interval evaluation of the tangent
 */
class NaturalIntervalFormTanh : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param n the node that we want the tan
 	 */
	NaturalIntervalFormTanh(NaturalIntervalFormNode *n)
	{
		_n = n;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormTanh()
	{
		delete _n;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return tanh(_n->eval());
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return tanh(_n->eval(b));
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return tanh(_n->evalLazy());
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = tanh(_n->value());
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval ni = _n->value();
		ni.intersect(atanh_rel(i, _n->value()));
		return _n->propagBackward(ni);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return _n->deriv(v) * Interval(1 + sqr(tanh(_n->eval())));
		// tanh(u)' = u' * (1 + tanh^2(u))
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return _n->derivLazy() * Interval(1 + sqr(tanh(_n->eval())));
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_n;

	// Copy protection
	NaturalIntervalFormTanh(const NaturalIntervalFormTanh & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormTanh & operator=(const NaturalIntervalFormTanh & x)
	{
	}
};



/**
 * @ingroup Interval
 * @class NaturalIntervalFormAtan
 * @brief Class for interval evaluation of the arc-tangent
 */
class NaturalIntervalFormAtanh : public NaturalIntervalFormNode
{
public:
	/**
 	 * Constructor
 	 * @param n the node that we want the atan
 	 */
	NaturalIntervalFormAtanh(NaturalIntervalFormNode *n)
	{
		_n = n;
	}

	/**
 	 * Destructor
 	 * @post the child is deleted
 	 */
	~NaturalIntervalFormAtanh()
	{
		delete _n;
	}

	/// @name Base class's virtual methods
	//@{
	bool toConstNodes(const RealVarImpl & x)
	{
		if (_n->toConstNodes(x)) {
			m_isConst = true;
			return true;
		} else {
			return false;
		}
	}

	FORM_RTYPE eval() CONST
	{
		return atanh(_n->eval());
	}

	FORM_RTYPE eval(Box *b) CONST
	{
		return atanh(_n->eval(b));
	}

	FORM_RTYPE evalLazy() CONST
	{
		if (this->isNotConstant()) {
			return atanh(_n->evalLazy());
		} else {
			return m_value;
		}
	}

	void evalForward()
	{
		_n->evalForward();
		m_value = atanh(_n->value());
	}

	virtual bool propagBackward(const Interval & i)
	{
		Interval ni = _n->value();
		ni.intersect(tanh(i));
		return _n->propagBackward(ni);
	}

	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		return _n->deriv(v) / Interval(1 + sqr(_n->eval()));
		// atanh(u)' = u' / (1 + u^2)
	}

	FORM_RTYPE derivLazy() CONST
	{
		if (this->isNotConstant()) {
			return _n->derivLazy() / Interval(1 + sqr(_n->eval()));
		} else {
			return Interval(0);
		}
	}
	//@}

private:
	NaturalIntervalFormNode *_n;

	// Copy protection
	NaturalIntervalFormAtanh(const NaturalIntervalFormAtanh & x) : NaturalIntervalFormNode(x)
	{
	}
	NaturalIntervalFormAtanh & operator=(const NaturalIntervalFormAtanh & x)
	{
	}
};

/**
 * @ingroup Interval
 * @class NaturalIntervalFormVisitor
 * @brief Class for visiting an expression and creating
 * the associated interval evaluation algorithm
 */
class NaturalIntervalFormVisitor : public RealExprVisitor
{
public:
	/// Constructor
	NaturalIntervalFormVisitor()
	{
	}

	/// Destructor
	~NaturalIntervalFormVisitor()
	{
	}

	/// @name Base class's virtual methods
	//@{
	void visit(RealExprRep & e);
	void visited(RealExprRepConst & e);
	void visited(RealExprRepIntervalConst & e);
	void visited(RealExprRepVar & e);
	void visited(RealExprRepAdd & e);
	void visited(RealExprRepMin & e);
	void visited(RealExprRepMax & e);
	void visited(RealExprRepSum & e);
	void visited(RealExprRepMul & e);
	void visited(RealExprRepProd & e);
	void visited(RealExprRepSub & e);
	void visited(RealExprRepOpp & e);
	void visited(RealExprRepDiv & e);
	void visited(RealExprRepSqr & e);
	void visited(RealExprRepSqrt & e);
	void visited(RealExprRepAbs & e);
	void visited(RealExprRepPow & e);
	void visited(RealExprRepLog & e);
	void visited(RealExprRepExp & e);
	void visited(RealExprRepCos & e);
	void visited(RealExprRepACos & e);
	void visited(RealExprRepSin & e);
	void visited(RealExprRepASin & e);
	void visited(RealExprRepTan & e);
	void visited(RealExprRepATan & e);
	void visited(RealExprRepCosh & e);
	void visited(RealExprRepACosh & e);
	void visited(RealExprRepSinh & e);
	void visited(RealExprRepASinh & e);
	void visited(RealExprRepTanh & e);
	void visited(RealExprRepATanh & e);
	//@}

	/// Returns the node for interval evaluation
	NaturalIntervalFormNode *node() const
	{
		return _node;
	}

private:
	NaturalIntervalFormNode *_node; // evaluator computed by the visitor
};



/**
 * @ingroup Interval
 * @class NaturalIntervalForm
 * @brief Class for natural interval evaluation of expressions
 */
class NaturalIntervalForm : public IntervalForm
{
public:
	/**
 	 * Constructor
 	 * @param e the real expression to evaluate
 	 * @param x RealVarImplementation used for lazy evaluation
 	 */
	NaturalIntervalForm (const RealExpr *e,
	                     const RealVarImpl *x = 0)
	{
		// Creation of the tree-like evaluator
		NaturalIntervalFormVisitor v;
		v.visit(*(e->const_rep()));
		_root = v.node();
		_v = x;
		if (_v != 0) _root->toConstNodes(*x);
	}

	/**
 	 * Destructor
 	 */
	~NaturalIntervalForm()
	{
		delete _root;
	}

	/**
 	 * Returns the lastly computed interval evaluation
 	 * it doesn't recompute
 	 */
	FORM_RTYPE value() const
	{
		return _root->value();
	}

	/**
 	 * Returns the interval evaluation
 	 * it computes the result
 	 */
	FORM_RTYPE eval() CONST
	{
		return _root->eval();
	}

	/**
 	 * Returns the interval evaluation over a box
 	 */
	FORM_RTYPE eval(Box *b) CONST
	{
		return _root->eval(b);
	}

	FORM_RTYPE evalLazy(const RealVarImpl & v) const
	{
		if ((_v == 0) || ((*_v) != v)) {
			return _root->eval();
		} else {
			return _root->evalLazy();
		}
	}

	/**
 	 * Evaluates the expression and saves each sub_term evaluation
 	 */
	void evalForward()
	{
		_root->evalForward();
	}

	bool propagBackward(const Interval & i)
	{
		return _root->propagBackward(i);
	}

	/**
 	 * Evaluates the derivative in forward mode wrt. v
 	 */
	FORM_RTYPE deriv(const RealVarImpl & v) CONST
	{
		if ((_v == 0) || ((*_v) != v)) {
			return _root->deriv(v);
		} else {
			return _root->derivLazy();
		}
	}
protected:
	// @var root node of the evaluatable expression
	NaturalIntervalFormNode *_root;

	// @var RealVarImplementation used for lazy evaluation
	const RealVarImpl *_v;
};



/**
 * @ingroup Interval
 * @class NaturalIntervalFormFactory
 * @brief Base class for the construction of an interval form
 */
class NaturalIntervalFormFactory : public IntervalFormFactory
{
public:
	/// Constructor
	NaturalIntervalFormFactory ()
	{
	}

	/// Destructor
	~NaturalIntervalFormFactory ()
	{
	}

	/**
 	 * Construction of an interval form
 	 * @param the real expression that want an evaluatable form
 	 * @param v the RealVarImplementation used for lazy evaluation
 	 */
	IntervalForm *create(const RealExpr *e,
	                     const RealVarImpl *v) const
	{
		return new NaturalIntervalForm(e, v);
	}


	/** Construction of an interval form
 	 * @param the real expression that want an evaluatable form
 	 */
	IntervalForm *create(const RealExpr *e) const
	{
		return new NaturalIntervalForm(e);
	}
};


END_NAMESPACE_ELISA


#endif // _ELISA_NATURAL_INTERVAL_FORM_H
